package com.alks.function.service.impl.stockdept.pcfactorystockquery;

import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.dto.SysUserTokenDTO;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.utils.FieldUtils;
import com.alks.common.utils.beanutils.ArrayUtils;
import com.alks.common.utils.beanutils.BeanUtil;
import com.alks.entity.data.entity.PcStitchProdDetail;
import com.alks.entity.data.entity.PcStitchSupplementProd;
import com.alks.entity.data.entity.PcSupplementDetail;
import com.alks.entity.data.entity.PcSupplementHead;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.StcSupDto;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.StcSupLotDto;
import com.alks.function.data.request.stockdept.pcfactorystockwork.StcSupRequest;
import com.alks.function.data.request.stockdept.pcfactorystockwork.StcSupUpRequest;
import com.alks.function.mapper.chengKong.PcStitchProdDetailMapper;
import com.alks.function.mapper.stockdept.pcfactorystockquery.SD_SQ_PcStitchSupplementProdMapper;
import com.alks.function.mapper.stockdept.pcfactorystockquery.SD_SQ_PcSupplementDetailMapper;
import com.alks.function.mapper.stockdept.pcfactorystockquery.SD_SQ_PcSupplementHeadMapper;
import com.alks.function.service.stockdept.pcfactorystockquery.IStcSupService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import io.swagger.models.auth.In;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
@Slf4j
@RequiredArgsConstructor
public class StcSupServiceImpl extends ServiceImpl<SD_SQ_PcStitchSupplementProdMapper, PcStitchSupplementProd> implements IStcSupService {
    private final SD_SQ_PcStitchSupplementProdMapper mapper;
    private final SD_SQ_PcSupplementHeadMapper suppHeadMapper;
    private final SD_SQ_PcSupplementDetailMapper suppDetailMapper;
    private final PcStitchProdDetailMapper prodDetailMapper;

    @Override
    @AutoPageAop
    public ResponseInfo getStcSupQuery(StcSupRequest request) {
        /*获取数据*/
        List<StcSupDto> dtos = mapper.getStcSupQuery(request);
        Page<StcSupDto> page = (Page<StcSupDto>) dtos;
        /*封装数据*/
        Map<String, Object> map = new HashMap<>(2);
        map.put("dtos", dtos);
        map.put("total", page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo getStcSupLotQuery(String lotNo) {
        /*获取数据*/
        List<StcSupLotDto> dtos = mapper.getStcSupLotQuery(lotNo);
        return ResponseInfo.ok(dtos);
    }

    @Override
    public ResponseInfo stcSupAdd(PcStitchSupplementProd request) {
        SysUserTokenDTO userTokenDTO = UserIdThread.get();
        String companyId = userTokenDTO.getCompanyId();
        /*补单号校验*/
        if (StringUtils.isBlank(request.getSlipNo())){
            throw new ServiceErrorException("单据号不能为空");
        }
        LambdaQueryWrapper<PcSupplementHead> headWrapper = new LambdaQueryWrapper<PcSupplementHead>()
                .eq(PcSupplementHead::getCompanyId,companyId)
                        .eq(PcSupplementHead::getSlipNo,request.getSlipNo());
        List<PcSupplementHead> heads = suppHeadMapper.selectList(headWrapper);
        if (ArrayUtils.isEmpyt(heads)){
            throw new ServiceErrorException("单据号不存在");
        }
        if (request.getSlipDate()==null){
            request.setSlipDate(LocalDate.now());
        }
        /*如果空数据则补充创建时间*/
        request.setCompanyId(companyId);
        request.setSysUser(userTokenDTO.getUserName());
        request.setSysDate(LocalDateTime.now());
        /*写入新数据*/
        mapper.insert(request);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo stcSupUpdate(PcStitchSupplementProd request) {
        PcStitchSupplementProd prod = mapper.selectById(request.getId());
        request.setSysDate(prod.getSysDate());
        request.setLotNo(prod.getLotNo());
        request.setSlipNo(prod.getSlipNo());
        updateCheck(request);
        /*更新数据*/
        lambdaUpdate().eq(PcStitchSupplementProd::getId,request.getId())
                .set(PcStitchSupplementProd::getQty,request.getQty())
                .set(PcStitchSupplementProd::getRemark,request.getRemark())
                .set(PcStitchSupplementProd::getDeptName,request.getDeptName())
                .set(PcStitchSupplementProd::getDeptNo,request.getDeptNo())
                .update();
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo stcSupDelete(Integer id) {
        PcStitchSupplementProd prod = mapper.selectById(id);
        /*重新补充值*/
        if (prod.getQty()>0) {
            prod.setQty(0f);
            updateCheck(prod);
        }
        mapper.deleteById(id);
        return ResponseInfo.ok();

    }

    @Override
    public ResponseInfo stitchSuppBack(String slipNo) {
        List<StcSupDto> dtoList = suppHeadMapper.stitchSuppBack(slipNo,UserIdThread.get().getCompanyId());
        return ResponseInfo.ok(dtoList);
    }

    /**
     * 修改数据检查
     * @param prod 修改后数据（QTY需要传入修改后值 如果是删除则传入0）
     */
    private void updateCheck(PcStitchSupplementProd prod){
        String companyId = UserIdThread.get().getCompanyId();
        // 1.次日数据不可修改
        if (!prod.getSysDate().toLocalDate().equals(LocalDate.now())){
            throw new ServiceErrorException("非当日数据不能修改");
        }
        BigDecimal prodQty = prod.getQty()==null?BigDecimal.ZERO:BigDecimal.valueOf(prod.getQty());
        // 2.数量不能低于已报账最大值
        /*获取已收总数(不包含当前数据)*/
        LambdaQueryWrapper<PcStitchSupplementProd> wrapper = new LambdaQueryWrapper<PcStitchSupplementProd>()
                .eq(PcStitchSupplementProd::getLotNo, prod.getLotNo())
                .eq(PcStitchSupplementProd::getCompanyId, companyId)
                .ne(PcStitchSupplementProd::getId, prod.getId());
        List<PcStitchSupplementProd> prods = mapper.selectList(wrapper);
        BigDecimal totalQty = BigDecimal.ZERO;
        if (prod.getId()!=null) {
            if (ArrayUtils.isNoEmpyt(prods)) {
                double sum = prods.stream()
                        .filter(a -> a.getSlipDate() != null && a.getSlipDate().equals(prod.getSlipDate()))
                        .filter(a -> a.getQty() != null)
                        .mapToDouble(PcStitchSupplementProd::getQty)
                        .sum();
                totalQty = BigDecimal.valueOf(sum);
            }
            /*获取已报账阈值*/
            BigDecimal minQty = prodDetailMapper.thresholdByLotAndDate(prod.getLotNo(), prod.getSlipDate(), companyId);
            minQty = minQty==null?BigDecimal.ZERO:minQty;
            if (totalQty.add(prodQty).compareTo(minQty) < 0) {
                throw new ServiceErrorException("不能低于已报账数量");
            }
        }
        // 3.数量不能大于整个补单最大值
        LambdaQueryWrapper<PcSupplementDetail> wrapper1 = new LambdaQueryWrapper<PcSupplementDetail>()
                .select(PcSupplementDetail::getTotalQty)
                .eq(PcSupplementDetail::getSlipNo, prod.getSlipNo())
                .eq(PcSupplementDetail::getCompanyId, companyId);
        List<PcSupplementDetail> details = suppDetailMapper.selectList(wrapper1);
        if (ArrayUtils.isEmpyt( details)){
            throw new ServiceErrorException("订单明细不存在");
        }
        BigDecimal maxQty = details.stream()
                .filter(Objects::nonNull)
                .map(PcSupplementDetail::getTotalQty)
                .filter(Objects::nonNull)
                .max(Float::compareTo)
                .map(BigDecimal::valueOf)
                .orElse(BigDecimal.ZERO);
        if (ArrayUtils.isNoEmpyt(prods)) {
            double sum = prods.stream()
                    .filter(Objects::nonNull)
                    .filter(a -> a.getQty() != null)
                    .mapToDouble(PcStitchSupplementProd::getQty).sum();
            totalQty = BigDecimal.valueOf(sum);
        }
        if (totalQty.add(prodQty).compareTo(maxQty)>0){
            throw new ServiceErrorException("不能大于补单最大值");
        }
    }
}
